package com.adjaisd.scarecrow.service.impl;

import com.adjaisd.scarecrow.dto.*;
import com.adjaisd.scarecrow.entity.Alarm;
import com.adjaisd.scarecrow.entity.Device;
import com.adjaisd.scarecrow.entity.Quota;
import com.adjaisd.scarecrow.mapper.AlarmMapper;
import com.adjaisd.scarecrow.repo.TimeSeriesRepository;
import com.adjaisd.scarecrow.service.AlarmService;
import com.adjaisd.scarecrow.service.DeviceService;
import com.adjaisd.scarecrow.service.QuotaService;
import com.adjaisd.scarecrow.vo.Pager;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author adjaisd
 * @since 2022-03-28
 */
@Service
public class AlarmServiceImpl extends ServiceImpl<AlarmMapper, Alarm> implements AlarmService {

    @Override
    public List<Alarm> getAlarmListByQId(long quotaId) {
        QueryWrapper<Alarm> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Alarm::getQuotaId, quotaId)
                .gt(Alarm::getCreateTime, 0L)
                .orderByDesc(Alarm::getLevel);
        return this.list(wrapper);
    }

    @Override
    public Alarm verifyQuota(QuotaDTO quotaDTO) {
        //1.根据指标id查询告警判断规则列表
        List<Alarm> alarmList = getAlarmListByQId(quotaDTO.getId());
        Alarm alarm = null;
        for (Alarm alarmEntity : alarmList) {
            // 判断：操作符和指标对比
            if ("String".equals(quotaDTO.getValueType()) || "Boolean".equals(quotaDTO.getValueType())) {
                if (alarmEntity.getOperator().equals("=") &&
                        quotaDTO.getStringValue().equals(alarmEntity.getThreshold().toString())) {
                    alarm = alarmEntity;
                    break;
                }
            } else {    // 数值
                if (alarmEntity.getOperator().equals(">") && quotaDTO.getValue() > alarmEntity.getThreshold()) {
                    alarm = alarmEntity;
                    break;
                }
                if (alarmEntity.getOperator().equals("<") && quotaDTO.getValue() < alarmEntity.getThreshold()) {
                    alarm = alarmEntity;
                    break;
                }
                if (alarmEntity.getOperator().equals("=") && quotaDTO.getValue().equals(alarmEntity.getThreshold())) {
                    alarm = alarmEntity;
                    break;
                }
            }
        }
        return alarm;
    }


    @Override
    public DeviceInfoDTO verifyDeviceInfo(DeviceInfoDTO deviceInfoDTO) {
        // 封装指标的告警  封装设备的告警
        DeviceStatusDTO deviceDTO = deviceInfoDTO.getDeviceStatusDTO();

        deviceDTO.setAlarmLevel(0); // 假设不告警
        deviceDTO.setAlarm(false);
        deviceDTO.setAlarmName("正常");
        deviceDTO.setStatus(true);
        deviceDTO.setOnline(true);

        for (QuotaDTO quotaDTO : deviceInfoDTO.getQuotaDTOList()) {
            Alarm alarm = verifyQuota(quotaDTO);// 根据指标得到告警信息
            if (alarm != null) {  // 如果指标存在告警
                quotaDTO.setAlarm("1");
                quotaDTO.setAlarmName(alarm.getName());     // 告警名称
                quotaDTO.setAlarmLevel(alarm.getLevel());   // 告警级别
                quotaDTO.setAlarmWebHook(alarm.getWebhook());// 告警web钩子
                quotaDTO.setCycle(alarm.getCycle());        // 沉默周期

                if (alarm.getLevel() > deviceDTO.getAlarmLevel()) {
                    deviceDTO.setAlarmLevel(alarm.getLevel());
                    deviceDTO.setAlarm(true);
                    deviceDTO.setAlarmName(alarm.getName());
                }
            } else {    // 如果指标不存储在告警
                quotaDTO.setAlarm("0");
                quotaDTO.setAlarmName("正常");
                quotaDTO.setAlarmLevel(0);
                quotaDTO.setAlarmWebHook("");
                quotaDTO.setCycle(0);
            }
        }
        return deviceInfoDTO;
    }

    @Autowired
    QuotaService quotaService;

    @Override
    public List<Alarm> getAlarmListByUID(long userId) {
        List<Quota> quotaList = quotaService.getQuotaListByUID(userId);
        List<Long> qidList = quotaList.stream().map(Quota::getId).collect(Collectors.toList());
        if (qidList.size() == 0) return new LinkedList<>();

        QueryWrapper<Alarm> wrapper = new QueryWrapper<>();
        wrapper.lambda()
                .in(Alarm::getQuotaId, qidList)
                .gt(Alarm::getCreateTime, 0L)
                .orderByDesc(Alarm::getQuotaId);
        return this.list(wrapper);
    }

    @Override
    public boolean existAlarmByQID(Long id) {
        QueryWrapper<Alarm> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Alarm::getQuotaId, id)
                .gt(Alarm::getCreateTime, 0L);
        return this.list(wrapper).size() > 0;
    }

    @Autowired
    AlarmMapper alarmMapper;

    @Override
    public boolean addAlarm(Alarm alarm) {
        return alarmMapper.insert(alarm) > 0;
    }

    @Override
    public Alarm getAlarm(Long quotaId, String name, String operator) {
        QueryWrapper<Alarm> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(Alarm::getName, name)
                .eq(Alarm::getOperator, operator)
                .eq(Alarm::getQuotaId, quotaId);
        List<Alarm> alarms = this.list(wrapper);
        if (alarms.size() == 0) return null;
        else return alarms.get(0);
    }

    @Override
    public boolean delAlarm(Long quotaId, String name, String operator) {
        Alarm alarm = getAlarm(quotaId, name, operator);
        if (alarm == null) return false;
        alarm.setCreateTime(0L);
        return alarmMapper.updateById(alarm) > 0;
    }

    @Autowired
    TimeSeriesRepository timeSeriesRepository;

    @Autowired
    DeviceService deviceService;

    @Override
    public Pager<QuotaAllInfo> queryAlarmLogByUID(Long userId, Long page, Long pageSize, String start, String end, String alarmName, String deviceId) {
        // 根据用户ID或deviceId构造设备ID限定语句
        LinkedList<Long> deviceIdList = new LinkedList<>();
        if (!Strings.isNullOrEmpty(deviceId)) { // 设备ID存在
            deviceIdList.add(Long.valueOf(deviceId));
        } else {    // 设备ID不存在，需根据用户ID查找设备ID
            List<Device> deviceList = deviceService.getDeviceListByUID(userId);
            List<Long> collect = deviceList.stream().map(Device::getId).collect(Collectors.toList());
            deviceIdList.addAll(collect);
        }
        List<String> list = new LinkedList<>();
        deviceIdList.forEach(id -> list.add(id + ""));
        String join = String.join("|", list);

        // 构造
        StringBuilder ql = new StringBuilder("where alarm='1' ");
        if (!Strings.isNullOrEmpty(start))
            ql.append("and time>='" + start + "' ");
        if (!Strings.isNullOrEmpty(end))
            ql.append("and time<='" + end + "' ");
        if (!Strings.isNullOrEmpty(alarmName))
            ql.append("and alarmName=~/" + alarmName + "/ ");
        if (deviceIdList.size() > 0)
            ql.append("and deviceId=~/^").append(join).append("$/ ");
        if (page == null || page == 0L) page = 1L;
        if (pageSize == null || pageSize == 0L) pageSize = 10L;

        //2.查询记录语句
        StringBuilder listQl = new StringBuilder("select * from quota  ");
        listQl.append(ql);
        listQl.append("order by desc limit " + pageSize + " offset " + (page - 1) * pageSize);

        //3.查询记录数语句
        StringBuilder countQl = new StringBuilder("select count(value) from quota ");
        countQl.append(ql);

        //4.执行查询记录语句
        List<QuotaAllInfo> quotaList = timeSeriesRepository.query(listQl.toString(), QuotaAllInfo.class);
        // 添加时间格式处理
        for (QuotaAllInfo quotaAllInfo : quotaList) {
            //2020-09-19T09:58:34.926Z   DateTimeFormatter.ISO_OFFSET_DATE_TIME
            //转换为 2020-09-19 09:58:34  格式
            LocalDateTime dateTime = LocalDateTime.parse(quotaAllInfo.getTime(), DateTimeFormatter.ISO_OFFSET_DATE_TIME);
            String time = dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"));
            quotaAllInfo.setTime(time);
        }

        //5.执行统计语句
        List<QuotaCount> quotaCount = timeSeriesRepository.query(countQl.toString(), QuotaCount.class);

        //6.封装返回结果
        if (quotaCount == null || quotaCount.size() == 0) {
            Pager<QuotaAllInfo> pager = new Pager<>(0L, 0L);
            pager.setPage(0);
            pager.setItems(Lists.newArrayList());
            return pager;
        } else {
            Long totalCount = quotaCount.get(0).getCount(); //总记录数
            Pager<QuotaAllInfo> pager = new Pager<>(totalCount, pageSize);
            pager.setPage(page);
            pager.setItems(quotaList);
            return pager;
        }
    }
}
